package us.wili.dev.client.service.impl;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import us.wili.dev.client.service.SmsService;
import us.wili.dev.client.util.JwtInfoUtils;
import us.wili.dev.common.config.QcloudSmsConfig;
import us.wili.dev.exception.AssertUtils;
import us.wili.dev.exception.ErrorCode;
import us.wili.dev.model.constants.SmsCacheKeyEnum;

import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

@Service
public class SmsServiceImpl implements SmsService {
    private static final String VERIFLY_CODE_CONTENT = "0123456789";


    @Autowired
    private QcloudSmsConfig qcloudSmsConfig;

    /**
     *     缓存发送短信的次数,有效时间一天
     */
    private static final Cache<String, Integer> SMS_SEND_TIME_CACHER = CacheBuilder.newBuilder()
            .expireAfterWrite(1, TimeUnit.DAYS)
            .maximumSize(1000)
            .build();

    /**
     * 每天发送短信的上限
     */
    private static final int MAX_SEND_SMS_TIME = 10;

    /**
     * 生成验证码
     */
    private Supplier<String> generateCode = () -> {
        StringBuilder code = new StringBuilder();
        for(int i=0; i < 4; i++) {
            code.append(VERIFLY_CODE_CONTENT.charAt(RandomUtils.nextInt(0,VERIFLY_CODE_CONTENT.length())));
        }
        return code.toString();
    };

    @Override
    public void sendVeriflyCode(String phone, SmsCacheKeyEnum emun) {
        int sendTime = Optional.ofNullable(SMS_SEND_TIME_CACHER.getIfPresent(phone)).orElse(0);
        AssertUtils.ifTrueThrow(sendTime >= MAX_SEND_SMS_TIME, ErrorCode.USER_SMS_SEND_TOO_MUCH);

        // 短信有效时间15分钟跟jwtInfoUtils的有效时间一致
        int smsMinute = 15;
        String code = generateCode.get();
        boolean isSuccess;
        switch (emun){
            case REGISTE_USER:
                isSuccess = qcloudSmsConfig.registerSms(phone, code, smsMinute);
                break;
            case CHANGE_PWD:
                isSuccess = qcloudSmsConfig.updatePwdSms(phone, code, smsMinute);
                break;
            default:
                isSuccess = false;
                break;
        }

        AssertUtils.ifFalseThrow(isSuccess, ErrorCode.USER_SMS_SEND_FAIL);
        SMS_SEND_TIME_CACHER.put(phone, sendTime + 1);
        JwtInfoUtils.cacheCaptcha( getVeriflyCodeKey(phone, emun), code);
    }

    @Override
    public void checkCodeOrFail(String phone, String code, SmsCacheKeyEnum emun) {
        JwtInfoUtils.verifyCaptcha(getVeriflyCodeKey(phone, emun), code);
    }

    /**
     * 获取缓存redis验证码的key
     * @param phone 相关手机号
     * @return 缓存redis验证码的key
     */
    private String getVeriflyCodeKey(String phone, SmsCacheKeyEnum emun) {
        return emun.getKey() + phone;
    }
}
